/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ServerPanel.java
 *
 * Created on 2011-08-13, 15:47:18
 */
package remotechessplayer;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author Jedrek
 */
class ServerPanel extends javax.swing.JPanel implements Runnable{

    Thread thread;
    
    SettingsPanel parent;
    ServerSocket serverSocket = null;
    List<MySocket> sockets;
    Socket chosenSocket = null;
    int port = -1;
    
    boolean connected = false;
    /** Creates new form ServerPanel */
    public ServerPanel(SettingsPanel parent) {
        super();
        this.parent = parent;
        sockets = new ArrayList<MySocket>();
        
        initComponents();
    }
    
    public boolean serverWorking(){
        if(serverSocket == null){
            return false;
        }
        return true;
    }
    
    @Override
    public void run() {
        while(!connected){
            for(int i = 0; i<sockets.size(); i++){
                try {
                    if(sockets.get(i).socket.getInputStream().read()<0){
                        sockets.remove(i--);
                        listConnections.setListData(sockets.toArray());
                    }
                } catch(SocketTimeoutException ex){
                    continue;
                } catch (IOException ex) {
                    sockets.remove(i--);
                    listConnections.setListData(sockets.toArray());
                } catch(Exception e){}  //czasami "index out of bounds" wyskakuje
            }
            try{
                MySocket socket = new MySocket();
                socket.socket = serverSocket.accept();
                sockets.add(socket);
                socket.socket.setSoTimeout(100);
                listConnections.setListData(sockets.toArray());
            } catch (IOException e){}
            catch(NullPointerException ex){
                return;
            }
//            listConnections.setListData(sockets.toArray());
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        jLabel1 = new javax.swing.JLabel();
        tbPort = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        listConnections = new javax.swing.JList();
        bStart = new javax.swing.JButton();
        bConnect = new javax.swing.JButton();
        lConnection = new java.awt.Label();

        setBorder(javax.swing.BorderFactory.createTitledBorder("Server settings"));
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setPreferredSize(new java.awt.Dimension(200, 295));

        jLabel1.setText("Port:");

        jLabel2.setText("Connections:");

        listConnections.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, listConnections, org.jdesktop.beansbinding.ObjectProperty.create(), listConnections, org.jdesktop.beansbinding.BeanProperty.create("elements"));
        bindingGroup.addBinding(binding);

        jScrollPane1.setViewportView(listConnections);

        bStart.setText("Start");
        bStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bStartActionPerformed(evt);
            }
        });

        bConnect.setText("Connect");
        bConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bConnectActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, 0, 0, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tbPort, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(bStart))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(bConnect))
                    .addComponent(lConnection, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(tbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(bStart))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(bConnect))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lConnection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(39, Short.MAX_VALUE))
        );

        bindingGroup.bind();
    }// </editor-fold>//GEN-END:initComponents

    private void bStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bStartActionPerformed
        if(serverSocket == null){
            try{
                port = Integer.parseInt(tbPort.getText());
            } catch(Exception e){
                tbPort.setText("");
                return;
            }
            try{
                serverSocket = new ServerSocket(port);
                serverSocket.setSoTimeout(300);

                parent.rbClient.setEnabled(false);
                parent.rbServer.setEnabled(false);
                bStart.setText("Stop");
                
                thread = new Thread(this);
                thread.start();
            } catch(Exception e){
                return;
            }
        } else{
            try{
                for(int i = 0; i<sockets.size(); i++)
                    if(sockets.get(i).socket != chosenSocket)
                        synchronized(sockets.get(i)){
                            sockets.get(i).socket.close();
                    }
                chosenSocket = null;
                serverSocket.close();
                serverSocket = null;

                parent.rbClient.setEnabled(true);
                parent.rbServer.setEnabled(true);
                bStart.setText("Start");
            } catch(Exception e){
                if(((RemoteChessPlayer)parent).showAlerts)
                    JOptionPane.showMessageDialog(null, "Couldn't close socket or server socket because: " + e.getMessage());
                return;
            }
        }
    }//GEN-LAST:event_bStartActionPerformed

    private void bConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bConnectActionPerformed
        if(!connected){
            MySocket socket = (MySocket)listConnections.getSelectedValue();
            if(socket == null)
                return;
            chosenSocket = socket.socket;
            try {
                chosenSocket.setSoTimeout(0);
            } catch (SocketException ex) {
            }
            //send message to chosen host
            try{
                OutputStream out = chosenSocket.getOutputStream();
                byte[] data = new byte[1];
                data[0] = RemoteChessPlayer.YOU_ARE_THE_CHOSEN_ONE;
                out.write(data);
            } catch (IOException ex){
                if(((RemoteChessPlayer)parent).showAlerts)
                    JOptionPane.showMessageDialog(null, "Couldn't communicate because: " + ex.getMessage());
                return;
            }

            //close all other connections
            for(int i = 0; i<sockets.size(); i++){
                if(sockets.get(i).socket != socket.socket){
                    try {
                        synchronized(sockets.get(i)){
                            sockets.get(i).socket.close();
                        }
                    } catch (IOException ex) {
                        if(((RemoteChessPlayer)parent).showAlerts)
                            JOptionPane.showMessageDialog(null, "Couldn't close socket because: " + ex.getMessage());
                    }
                }
                sockets.remove(i--);
            }
            listConnections.setListData(sockets.toArray());
            //submit connetion
            ((RemoteChessPlayer)parent).submitConnection();

            MySocket mySocket = new MySocket();
            mySocket.socket = chosenSocket;
            lConnection.setText(mySocket.toString());
            bConnect.setText("Disconnect");
        } else{
            try {
                chosenSocket.close();
            } catch (IOException ex) {
            }
            chosenSocket = null;
            connected = false;
            bConnect.setText("Connect");
            lConnection.setText("");
        }
    }//GEN-LAST:event_bConnectActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    public javax.swing.JButton bConnect;
    private javax.swing.JButton bStart;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    public java.awt.Label lConnection;
    private javax.swing.JList listConnections;
    public javax.swing.JTextField tbPort;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
}
